<?php

namespace Config\Events;

/**
 * 用于检测业务代码死循环或者长时间阻塞等问题
 * 如果发现业务卡死，可以将下面declare打开（去掉//注释），并执行php start.php reload
 * 然后观察一段时间workerman.log看是否有process_timeout异常
 */

//declare(ticks=1);

use app\admin\model\Service;
use app\wechat\service\WechatService;
use Config\Db as DbConfig;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Workerman\Lib\Timer;
use \GatewayWorker\Lib\Db;
use \GatewayWorker\Lib\Gateway;

/**
 * 主逻辑
 * 主要是处理 onConnect onMessage onClose 三个方法
 * onConnect 和 onClose 如果不需要可以不用实现并删除
 */

//如果指定某个域名才能connect，请修改这里
//const HTTP_ORIGIN = '';

class Events
{
    /**
     * 新建一个类的静态成员，用来保存数据库实例
     *
     * @var \GatewayWorker\Lib\DbConnection
     */
    public static $db = null;
    /**
     * GlobalData\Client
     *
     * @var \GlobalData\Client
     */
    public static $global = null;
    /**
     * Config
     *
     * @var DbConfig
     */
    public static $global_cfg = null;

    /**
     * 客服id前缀
     */
    const SERVICE_USER_PREFIX = 'KF';

    /**
     * 进程启动后初始化数据库连接
     */
    public static function onWorkerStart($worker)
    {
        if (empty(self::$db)) {
            self::$db = Db::instance('db'); //数据库链接
        }
        if (empty(self::$global_cfg)) {
            self::$global_cfg = DbConfig::$config; //分布式数据配置
        }
        if (empty(self::$global)) {
            self::$global = new \GlobalData\Client(self::$global_cfg['globalData']);
            // 客服列表
            if (is_null(self::$global->kfList)) {
                self::$global->kfList = [];
            }
            // 会员列表[动态的，这里面只是目前未被分配的会员信息]
            if (is_null(self::$global->userList)) {
                self::$global->userList = [];
            }
            // 管理员列表
            if (is_null(self::$global->adminList)) {
                self::$global->adminList = [];
            }
            // 会员以 uid 为key的信息简表,只有在用户退出的时候，才去执行修改
            if (is_null(self::$global->uidSimpleList)) {
                self::$global->uidSimpleList = [];
            }
            // 会员以 uid 为key的信息简表,只有在用户退出的时候，才去执行修改
            if (is_null(self::$global->message_template)) {
                $message_template = Collection::make(self::$db->query("SELECT * FROM `ws_message_template` WHERE `deleted_at` IS NULL"));
                self::$global->add('message_template', $message_template);
            }
            //把全部客服加进内存
            if (is_null(self::$global->kfSimleList)) {
                $kfSimleList = Collection::make(self::$db->query("SELECT `id`, `user_name`, `role`, `user_avatar`, `openid` FROM `ws_services`"))->keyBy('id')->toArray();
                self::$global->add('kfSimleList', $kfSimleList);
            }

            // 当天的累积接入值
            $key = date('Ymd') . 'total_in';
            if (is_null(self::$global->$key)) {
                self::$global->$key = 0;

                $oldKey = date('Ymd', strtotime('-1 day')) . 'total_in'; // 删除前一天的统计值
                unset(self::$global->$oldKey);
                unset($oldKey, $key);
            }
            // 成功接入值
            $key = date('Ymd') . 'success_in';
            if (is_null(self::$global->$key)) {
                self::$global->$key = 0;

                $oldKey = date('Ymd', strtotime('-1 day')) . 'success_in'; // 删除前一天的统计值
                unset(self::$global->$oldKey);
                unset($oldKey, $key);
            }
        }

        // 定时统计数据
        if (0 === $worker->id) {
            // 1分钟统计一次实时数据
            Timer::add(60 * 1, function () {
                self::writeLog(1);
            });
            // 40分钟写一次当前日期点数的log数据
            Timer::add(60 * 40, function () {
                self::writeLog(2);
            });
        }
    }

    /**
     * @param $service_id
     */
    private static function getServiceInfo($service_id)
    {
        if (!$service_id) {
            return [];
        }
        if (array_key_exists($service_id, self::$global->kfSimleList)) {
            return self::$global->kfSimleList[$service_id];
        }
        $id = intval(str_replace(self::SERVICE_USER_PREFIX, '', $service_id));
        $kf = self::$db->row("SELECT `id`, `user_name`, `role`, `user_avatar`, `openid` FROM `ws_services` WHERE id = {$id}");
        if (!$kf) {
            return [];
        }
        do {
            $kfSimleList = $old = self::$global->kfSimleList;
            $kfSimleList[$service_id] = $kf;
        } while (!self::$global->cas('kfSimleList', $old, $kfSimleList));
        return $kf;
    }
    /**
     * 当客户端连接时触发
     * 如果业务不需此回调可以删除onConnect
     *
     * @param int $client_id 连接id
     */
    public static function onConnect($client_id)
    {
        // $client_id->onWebSocketConnect = function($client_id , $http_header)
        // {
        //     // 可以在这里判断连接来源是否合法，不合法就关掉连接
        //     // $_SERVER['HTTP_ORIGIN']标识来自哪个站点的页面发起的websocket链接
        //     if($_SERVER['HTTP_ORIGIN'] != 'http://laykefu.guoshanchina.com')
        //     {
        //         $client_id->close();
        //     }
        //     // onWebSocketConnect 里面$_GET $_SERVER是可用的
        //     // var_dump($_GET, $_SERVER);
        // };
    }

    /**
     * 当客户端发来消息时触发
     * @param int   $client_id 连接id
     * @param array $message   具体消息
     */
    public static function onMessage($client_id, $message)
    {
        $message = json_decode($message, true);
        switch ($message['type']) {
                // 客服初始化
            case 'init':
                $kfList = self::$global->kfList;
                // 如果该客服未在内存中记录则记录
                if (!array_key_exists($message['uid'], $kfList)) {
                    do {
                        $newKfList = $kfList;
                        $newKfList[$message['uid']] = [
                            'id' => $message['uid'],
                            'name' => $message['name'],
                            'avatar' => $message['avatar'],
                            'client_id' => $client_id,
                            'role' => $message['role'],
                            'task' => 0,
                            'user_info' => []
                        ];
                    } while (!self::$global->cas('kfList', $kfList, $newKfList));
                } elseif (isset($kfList[$message['uid']])) {
                    do {
                        $newKfList = $kfList;
                        $newKfList[$message['uid']]['client_id'] = $client_id;
                    } while (!self::$global->cas('kfList', $kfList, $newKfList));
                }
                $kf = $newKfList[$message['uid']];
                if ($kf['role'] == Service::ROLE_ADMIN) {
                    $adminList = self::$global->adminList;
                    if (!isset($adminList[$kf['id']])) {
                        do {
                            $_adminList = $adminList;
                            $_adminList[$kf['id']] = $kf;
                        } while (!self::$global->cas('adminList', $adminList, $_adminList));
                    }
                }
                unset($newKfList, $kfList);

                // 绑定 client_id 和 uid
                Gateway::bindUid($client_id, $message['uid']);

                // Gateway::sendToAll(json_encode($msg));
                self::dispatchService($kf);
                break;
                // 顾客初始化
            case 'userInit':
                $user = self::$db->row("SELECT * FROM `ws_users` WHERE `id` = {$message['uid']} LIMIT 1");
                if (!$user || 1 != $user['status']) {
                    //如果用户审核未通过, 打回去~
                    return self::sendToClient($client_id, [
                        'message_type' => 'unauthorized',
                        'data' => [
                            'content' => '请先完成注册手续后再咨询'
                        ]
                    ]);
                }

                if (1 != $user['enable']) {
                    return self::sendToClient($client_id, [
                        'message_type' => 'close',
                        'data' => [
                            'content' => '您已被禁用'
                        ]
                    ]);
                }
                dump("用户 {$user['nickname']} 上线");
                $userList = self::$global->userList;
                // 如果该顾客未在内存中记录则记录
                if (!array_key_exists($message['uid'], $userList)) {

                    // 写入接入值
                    $key = date('Ymd') . 'total_in';
                    self::$global->$key = 0;
                    do {
                        $oldKey = date('Ymd', strtotime('-1 day')); // 删除前一天的统计值
                        unset(self::$global->$oldKey);
                    } while (!self::$global->increment($key));
                    unset($key);
                }

                // 维护 UID对应的client_id 数组
                do {
                    $old = $newList = self::$global->uidSimpleList;
                    $newList[$message['uid']] = $client_id;
                } while (!self::$global->cas('uidSimpleList', $old, $newList));
                unset($old, $newList);
                $user = array_merge($user, self::userInfo($user, $client_id));
                do {
                    $NewUserList = $userList;
                    $NewUserList[$message['uid']] = $user;
                } while (!self::$global->cas('userList', $userList, $NewUserList));
                // 绑定 client_id 和 uid
                Gateway::bindUid($client_id, $message['uid']);
                // 尝试分配新会员进入服务
                // self::userOnlineTask($client_id, $message['group']);
                self::dispathUser($client_id, $user);
                unset($user);
                break;
                // 聊天
            case 'chatMessage':
                $client = Gateway::getClientIdByUid($message['data']['to_id']);
                if (!empty($client)) {
                    $chat_message = [
                        'message_type' => 'chatMessage',
                        'data' => [
                            'name' => $message['data']['from_name'],
                            'avatar' => $message['data']['from_avatar'],
                            'id' => $message['data']['from_id'],
                            'time' => date('Y-m-d H:i:s'),
                            'content' => htmlspecialchars($message['data']['content'])
                        ]
                    ];
                    Gateway::sendToClient($client['0'], json_encode($chat_message));
                    unset($chat_message);

                    // 聊天信息入库
                    $serviceLog = [
                        'from_id' => $message['data']['from_id'],
                        'from_name' => $message['data']['from_name'],
                        'from_avatar' => $message['data']['from_avatar'],
                        'to_id' => $message['data']['to_id'],
                        'to_name' => $message['data']['to_name'],
                        'content' => $message['data']['content'],
                        'time_line' => time()
                    ];

                    self::$db->insert('ws_chat_log')->cols($serviceLog)->query();
                    unset($serviceLog);
                }
                break;
            case 'userSend':
                if (!isset(self::$global->userList[$message['data']['from_id']])) {
                    return false;
                }
                $user = self::$global->userList[$message['data']['from_id']];
                if (empty($user['service_ids'])) {
                    return self::sendToClient($client_id, [
                        'message_type' => 'close',
                        'data' => [
                            'content' => '尚未配置在线客服,请联系线下人员处理..'
                        ]
                    ]);
                }
                self::$db->insert('ws_chat_log')->cols([
                    'from_id' => $message['data']['from_id'],
                    'from_name' => $message['data']['from_name'],
                    'from_avatar' => $message['data']['from_avatar'],
                    'to_id' => $message['data']['to_id'],
                    'to_name' => $message['data']['to_name'],
                    'content' => $message['data']['content'],
                    'user_id' => $user['id'],
                    'time_line' => time()
                ])->query();
                self::callServiceUpline($user['service_ids'], $user);
                $services = self::userOnlineServices($user['service_ids']);
                $client_ids = array_column($services, 'client_id');
                if ($client_ids) {
                    self::sendToAll([
                        'message_type' => 'userSend',
                        'data' => [
                            'name' => $message['data']['from_name'],
                            'avatar' => $message['data']['from_avatar'],
                            'id' => $message['data']['from_id'],
                            'time' => date('Y-m-d H:i:s'),
                            'content' => htmlspecialchars($message['data']['content']),
                            'user' => $user
                        ]
                    ], $client_ids);
                } else {
                    self::autoSend($user);
                    // && self::sendToClient($client_id, ['message_type' => 'wait', 'data' => ['content' => '已为您通知客服上线']]);
                }
                unset($services, $client_ids, $user);
                break;
            case 'sendToUser':
                $id = $message['data']['to_id'];
                $user = self::$global->userList[$id] ?? [];
                if (!$user || empty($user['client_id'])) {
                    self::sendToClient($client_id, [
                        'message_type' => 'userOffLine',
                        'content' => '用户已下线',
                        'uid' => $id
                    ]);
                    // break;
                    $user = self::$db->row("SELECT * FROM `ws_users` WHERE `id` = {$id} LIMIT 1") ?: [];
                    $user = array_merge($user, self::userInfo($user, ''));
                    self::callUserUpline($user);
                }

                $client_ids = [$user['client_id']];
                $services = self::userOnlineServices($user['service_ids'], $message['data']['from_id']);
                $services && $client_ids = array_merge($client_ids, array_column($services, 'client_id'));
                $client_ids = array_filter($client_ids);
                self::sendToAll([
                    'message_type' => 'sendToUser',
                    'data' => [
                        'name' => $message['data']['from_name'],
                        'avatar' => $message['data']['from_avatar'],
                        'id' => $user['id'],
                        'time' => date('Y-m-d H:i:s'),
                        'from' => $message['data']['from_id'],
                        'content' => htmlspecialchars($message['data']['content']),
                        'user' => $user
                    ]
                ], $client_ids);
                self::$db->insert('ws_chat_log')->cols([
                    'from_id' => $message['data']['from_id'],
                    'from_name' => $message['data']['from_name'],
                    'from_avatar' => $message['data']['from_avatar'],
                    'to_id' => $message['data']['to_id'],
                    'to_name' => $message['data']['to_name'],
                    'content' => $message['data']['content'],
                    'user_id' => $user['id'],
                    'time_line' => time()
                ])->query();
                unset($client_ids);
                break;
                // 转接
            case 'changeGroup':
                // 通知客户端转接中
                break;
            case 'closeUser':
                $user = Arr::get(self::$global->userList, $message['uid']);
                if ($user) {
                    self::userOnlineServices($user['service_ids'] ?? [], $message['kfid'])
                        || self::sendToClient($user['client_id'], ['message_type' => 'wait', 'data' => ['content' => '暂时没有客服上班,请稍后再咨询。']]);
                }
                unset($user);
                break;
            case 'ping':
                if (isset($message['data']['l_user_id'])) {
                    $user = self::$db->row("SELECT `status` FROM `ws_services` WHERE `id`={$message['data']['l_user_id']} LIMIT 1");
                    if (2 == $user['status']) {
                        $userInfo = self::$global->uidSimpleList;
                        if (isset($userInfo[$message['uid']])) {
                            Gateway::sendToClient($userInfo[$message['uid']], json_encode(['message_type' => 'close']));
                        }
                    }
                }
                break;
        }
    }

    private static function userInfo($user, $client_id)
    {
        return [
            'shop' => self::getServiceInfo($user['shop_id']),
            'department' => self::getServiceInfo($user['department_id']),
            'service' => self::getServiceInfo($user['service_id']),
            'market' => self::getServiceInfo($user['market_id']),
            'client_id' => $client_id,
            'avatar' => $user['headimgurl'],
            'name' => $user['name'] ?: $user['nickname'],
            'ip' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '',
            'service_ids' => array_filter([
                self::SERVICE_USER_PREFIX . $user['service_id'],
                self::SERVICE_USER_PREFIX . $user['shop_id'],
                self::SERVICE_USER_PREFIX . $user['market_id'],
                self::SERVICE_USER_PREFIX . $user['department_id']
            ], fn ($id) => self::SERVICE_USER_PREFIX != $id)
        ];
    }
    /**
     * 自动回复
     */
    public static function autoSend($user): bool
    {
        //自动回复
        $sayHello = self::$db->row('select `word`,`status` from `ws_reply` where `id` = 1');
        if (!empty($sayHello) && 1 == $sayHello['status'] && !empty($user['service'])) {
            $hello = [
                'message_type' => 'helloMessage',
                'data' => [
                    'name' => $user['service']['user_name'],
                    'avatar' => $user['service']['user_avatar'],
                    'id' => $user['id'],
                    'time' => date('Y-m-d H:i:s'),
                    'from' => $user['service_id'],
                    'content' => htmlspecialchars($sayHello['word']),
                    'user' => $user
                ]
            ];
            self::sendToClient($user['client_id'], $hello);
            self::$db->insert('ws_chat_log')->cols([
                'from_id' => $hello['data']['from'],
                'from_name' => $hello['data']['name'],
                'from_avatar' => $hello['data']['avatar'],
                'to_id' => $hello['data']['id'],
                'to_name' => $user['name'],
                'content' => $hello['data']['content'],
                'user_id' => $user['id'],
                'time_line' => time()
            ])->query();
            return true;
        }
        return false;
    }

    /**
     * 当用户断开连接时触发
     * tips: 当服务端主动退出的时候，会出现 exit status 9.原因是：服务端主动断开之后，连接的客户端会走这个方法，而短时间内进程
     * 需要处理这多的逻辑，又有cas操作，导致进程退出会超时，然后会被内核杀死，从而报出错误 9.实际对真正的业务没有任何的影响。
     * @param  int    $client_id 连接id
     * @return void
     */
    public static function onClose($client_id)
    {
        $uidSimpleList_old = $uidSimpleList_new = self::$global->uidSimpleList;
        $userList_old = $userList_new = self::$global->userList;
        $kfList_old = $kfList_new = self::$global->kfList;
        $adminList_old = $adminList_new = self::$global->adminList;
        $user_id = array_search($client_id, $uidSimpleList_new);
        //是客户退出
        if (false !== $user_id) {
            unset($uidSimpleList_new[$user_id]);
            while (!self::$global->cas('uidSimpleList', $uidSimpleList_old, $uidSimpleList_new));
            $user = $userList_new[$user_id] ?? null;
            if ($user) {
                self::$db->query("update `ws_service_log` set `end_time` = " . time() . " where `client_id`= '" . $client_id . "'");
                //找当前用户的客服
                $services = self::userOnlineServices($user['service_ids']);
                if ($services) {
                    foreach ($services as $service) {
                        $service['user_info'] = array_diff($service['user_info'], [$user_id]);
                        $service['task'] = count($service['user_info']);
                        $kfList_new[$service['id']] = $service;
                        //通知客服用户已下线
                        self::sendToClient($service['client_id'], ['message_type' => 'delUser', 'data' => ['id' => $user_id]]);
                    }
                }
                unset($userList_new[$user_id]);
                while (!self::$global->cas('userList', $userList_old, $userList_new));
            }
        } else {
            if ($kfList_new) {
                foreach ($kfList_new as $key => $vo) {
                    if ($client_id == $vo['client_id']) {
                        unset($kfList_new[$key]);
                        if ($id = intval(trim($vo['id'], self::SERVICE_USER_PREFIX))) {
                            self::$db->query("update `ws_services` set online = 2 where id = {$id}");
                        }
                        if ($vo['user_info']) {
                            foreach ($vo['user_info'] as $userId) {
                                self::sendToClient($userId, [
                                    'message_type' => 'kf_offline',
                                    'kf_id' => $vo['id'],
                                    'kf_name' => $vo['name']
                                ]);
                            }
                        }
                        if (isset($adminList_new[$key])) {
                            unset($adminList_new[$key]);
                        }
                        break;
                    }
                }
            }
        }

        while (!self::$global->cas('kfList', $kfList_old, $kfList_new));
        while (!self::$global->cas('adminList', $adminList_old, $adminList_new));
    }

    /**
     * 将内存中的数据写入统计表
     * @param int $flag
     */
    private static function writeLog($flag = 1)
    {
        // 上午 8点 到 22 点开始统计
        if (date('H') < 8 || date('H') > 22) {
            return;
        }

        // 当前正在接入的人 和 在线客服数
        $kfList = self::$global->kfList;

        $nowTalking = 0;
        $onlineKf = 0;
        if (!empty($kfList)) {
            foreach ($kfList as $key => $vo) {
                $nowTalking += count($vo['user_info']);
            }
        }

        // 在队列中的用户
        $inQueue = count(self::$global->userList);

        $key = date('Ymd') . 'total_in';
        $key2 = date('Ymd') . 'success_in';
        $param = [
            'is_talking' => $nowTalking,
            'in_queue' => $inQueue,
            'online_kf' => $onlineKf,
            'success_in' => self::$global->$key2,
            'total_in' => self::$global->$key,
            'now_date' => date('Y-m-d')
        ];
        self::$db->update('ws_now_data')->cols($param)->where('id=1')->query();

        if (2 == $flag) {
            $param = [
                'is_talking' => $nowTalking,
                'in_queue' => $inQueue,
                'online_kf' => $onlineKf,
                'success_in' => self::$global->$key2,
                'total_in' => self::$global->$key,
                'add_date' => date('Y-m-d'),
                'add_hour' => date('H'),
                'add_minute' => date('i')
            ];
            self::$db->insert('ws_service_data')->cols($param)->query();
        }
        unset($kfList, $nowTalking, $inQueue, $onlineKf, $key, $key2, $param);
    }

    /**
     * @param $client_id
     * @param $message
     */
    public static function sendToClient($client_id, $message)
    {
        if (!is_string($message)) {
            $message = json_encode($message);
        }
        return Gateway::sendToClient($client_id, $message);
    }

    /**
     * @param $message
     * @param $client_ids
     * @param null          $exclude_client_id
     * @param null          $raw
     */
    public static function sendToAll($message, $client_ids = null, $exclude_client_id = null, $raw = false)
    {
        if (!is_string($message)) {
            $message = json_encode($message);
        }
        return Gateway::sendToAll($message, $client_ids, $exclude_client_id, $raw);
    }

    /**
     * 分配用户
     *
     * @param  string $client_id
     * @param  int    $group
     * @param  array  $user
     * @return void
     */
    public static function dispathUser($client_id, array $user)
    {
        $service_ids = $user['service_ids'];
        $services = self::userOnlineServices($service_ids);
        self::logServiceLog($user);
        if ($services) {
            $kfList = $_kfList = self::$global->kfList;
            foreach ($services as $service_id => $kf) {
                self::sendToClient($client_id, [
                    'message_type' => 'connect',
                    'data' => [
                        'kf_id' => $kf['id'],
                        'kf_name' => $kf['name']
                    ]
                ]);
                self::sendToClient($kf['client_id'], [
                    'message_type' => 'connect',
                    'data' => [
                        'user_info' => $user
                    ]
                ]);
                $kf['user_info'][] = $client_id;
                $kf['user_info'] = array_unique($kf['user_info']);
                $kf['task'] = count($kf['user_info']);
                $kfList[$service_id] = $kf;
            }
            while (!self::$global->cas('kfList', $_kfList, $kfList));
        } else {
            // self::autoSend($user);
            // self::callServiceUpline($service_ids, $user)
            // && self::sendToClient($client_id, ['message_type' => 'wait', 'data' => ['content' => '已为您通知客服上线']]);
        }
    }

    /**
     * 服务信息入库
     *
     * @param  array  $user
     * @param  string $kf_id
     * @return void
     */
    private static function logServiceLog(array $user)
    {
        $kf_id = $user['service_id'] ?? 0;
        if (!$kf_id) {
            return false;
        }
        self::$db->query("DELETE FROM `ws_service_log` WHERE user_id = :user_id AND end_time = :end_time", ['user_id' => $user['id'], 'end_time' => 0]);
        self::$db->insert('ws_service_log')->cols([
            'user_id' => $user['id'],
            'client_id' => $user['client_id'],
            'user_name' => $user['name'],
            'user_ip' => $user['ip'],
            'user_avatar' => $user['avatar'],
            'kf_id' => $kf_id,
            'start_time' => time(),
            'end_time' => 0
        ])->query();
    }
    /**
     * @param $client_id
     * @param $kf
     */
    private static function dispatchService($kf)
    {
        //设置客服在线
        if ($id = intval(trim($kf['id'], self::SERVICE_USER_PREFIX))) {
            self::$db->query("update `ws_services` set online = 1 where id = {$id}");
        }
        // 客服上线通知在线用户
        $msg = [
            'message_type' => 'kf_online',
            'data' => [
                'kf_name' => $kf['name'],
                'kf_avatar' => $kf['avatar'],
                'kf_id' => $kf['id'],
                'kf_role' => $kf['role'],
                'time' => date('Y-m-d H:i:s')
            ]
        ];
        $service_id = $kf['id'];
        $userList = self::$global->userList;
        $kfList = $_kfList = self::$global->kfList;
        foreach ($userList as $user) {
            if (in_array($kf['id'], $user['service_ids'])) {
                //确认过眼神
                $client_id = $user['client_id'];
                $isOnline = self::sendToClient($client_id, $msg);
                if ($isOnline) {
                    self::sendToClient($kf['client_id'], [
                        'message_type' => 'connect',
                        'data' => [
                            'user_info' => $user
                        ]
                    ]);
                    $kf['user_info'][] = $client_id;
                    $kf['user_info'] = array_unique($kf['user_info']);
                    $kf['task'] = count($kf['user_info']);
                    $kfList[$service_id] = $kf;
                    // self::logServiceLog($user);
                }
            }
        }
        while (!self::$global->cas('kfList', $_kfList, $kfList)) {
        };
    }
    /**
     * 喊用户上线
     *
     * @return void
     */
    public static function callUserUpline(array $user)
    {
        $key = 'service_online_record:' . date('Y-m-d');
        if (is_null(self::$global->$key)) {
            self::$global->add($key, Collection::make());
            $old_key = 'service_online_record:' . date('Y-m-d', strtotime('-1 day'));
            unset(self::$global->$old_key);
        }
        /**
         * @var Collection
         */
        $service_online_record = clone self::$global->$key;
        if (!$service_online_record->has($user['id']) && !empty($user['openid'])) {
            if ($template = self::$global->message_template->where('title', '客服跟进提醒')->first()) {
                WechatService::sendTemplateMessage($user['openid'], $template['template_id'], null, [
                    'first' => "您好，我们是大成集团健康管理团队",
                    'keyword1' => $user['name'] ?: '尊敬的客户',
                    'keyword2' => date('Y-m-d H:i:s'),
                    'remark' => '您的健康管理团队已对您发起项目使用后的售后服务，请尽快上线回复哦 !'
                ]);
            }
            $service_online_record->put($user['id'], date('Y-m-d H:i:s'));
            while (!self::$global->cas($key, self::$global->$key, $service_online_record));
            return true;
        }
        return false;
    }

    /**
     * 喊客服上线
     *
     * @return void
     */
    public static function callServiceUpline(array $service_ids, array $user)
    {
        $key = 'user_online_record:' . date('Y-m-d');
        $sended = false;
        if (is_null(self::$global->$key)) {
            self::$global->add($key, Collection::make());
            $old_key = 'user_online_record:' . date('Y-m-d', strtotime('-1 day'));
            unset(self::$global->$old_key);
        }
        $old = self::$global->$key;
        /**
         * @var Collection
         */
        $user_online_record = clone $old;
        if (!$user_online_record->has($user['id'])) {
            foreach ($service_ids as $service_id) {
                if (self::serviceIsOnline($service_id)) continue;
                $service_id = intval(str_replace(self::SERVICE_USER_PREFIX, '', $service_id));
                $service = self::$db->row("SELECT * FROM ws_services WHERE id = {$service_id} LIMIT 1");
                // 门店跟销售才提醒
                // if (!in_array($service['role'], [Service::ROLE_MARKET, Service::ROLE_SHOP])) continue;
                if (empty($service['openid'])) continue;
                if ($template = self::$global->message_template->where('title', '客服跟进提醒')->first()) {
                    WechatService::sendTemplateMessage($service['openid'], $template['template_id'], null, [
                        'first' => "您好, " . $service['user_name'],
                        'keyword1' => $user['name'] ?: '匿名客户',
                        'keyword2' => date('Y-m-d H:i:s'),
                        'remark' => '请尽快上线答复客户'
                    ]);
                    $user_online_record->put($user['id'], date('Y-m-d H:i:s'));
                    $sended = true;
                }
            }
        }

        if ($sended) {
            while (!self::$global->cas($key, $old, $user_online_record));
        }
        return $sended;
    }

    /**
     * 获取用户在线的客服
     *
     * @param  array   $service_ids
     * @param  int     $ignore_id
     * @return array
     */
    private static function userOnlineServices(array $service_ids, $ignore_id = null)
    {
        $admin = self::$global->adminList;
        if ($admin) {
            $service_ids = array_merge($service_ids, array_keys($admin));
        }
        if ($ignore_id) {
            $service_ids = array_diff($service_ids, [$ignore_id]);
        }
        return Arr::only(self::$global->kfList, $service_ids);
    }

    /** 
     * 客服在不在线
     */
    private static function serviceIsOnline($id)
    {
        return !empty(self::$global->kfList[$id]['client_id']);
    }
}
